/******************************************************************************
 * Product: Adempiere ERP & CRM Smart Business Solution                       *
 * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.                *
 * This program is free software; you can redistribute it and/or modify it    *
 * under the terms version 2 of the GNU General Public License as published   *
 * by the Free Software Foundation. This program is distributed in the hope   *
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.           *
 * See the GNU General Public License for more details.                       *
 * You should have received a copy of the GNU General Public License along    *
 * with this program; if not, write to the Free Software Foundation, Inc.,    *
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.                     *
 * For the text or an alternative of this public license, you may reach us    *
 * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA        *
 * or via info@compiere.org or http://www.compiere.org/license.html           *
 *****************************************************************************/
package org.compiere.acct;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.MAccount;
import org.compiere.model.MAccountCombination;
import org.compiere.model.MAcctSchema;
import org.compiere.model.MConversionRate;
import org.compiere.model.MCostDetail;
import org.compiere.model.MCurrency;
import org.compiere.model.MFactAcct;
import org.compiere.model.MJournal;
import org.compiere.model.MJournalBatch;
import org.compiere.model.MJournalLine;
import org.compiere.model.MTable;
import org.compiere.model.Mhrmpayment;
import org.compiere.model.MInvoiceLine;
import org.compiere.model.MLandedCostAllocation;
import org.compiere.model.Mhrmpaymentline;
import org.compiere.model.Mhrmpaymentlist;
import org.compiere.model.ProductCost;
import org.compiere.model.X_C_Period;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.eevolution.model.X_HR_Employee;
import org.joda.time.DateTime;

import extend.org.compiere.utils.Util;

/**
 *  Post Invoice Documents.
 *  <pre>
 *  Table:              C_Invoice (318)
 *  Document Types:     ARI, ARC, ARF, API, APC
 *  </pre>
 *  @author Jorg Janke
 *  @author Armen Rizal, Goodwill Consulting
 *  	<li>BF: 2797257	Landed Cost Detail is not using allocation qty
 *  
 *  @version  $Id: Doc_Invoice.java,v 1.2 2006/07/30 00:53:33 jjanke Exp $
 */
public class Doc_hrmpayment extends Doc
{
	/**
	 *  Constructor
	 * 	@param ass accounting schemata
	 * 	@param rs record
	 * 	@param trxName trx
	 */
	public Doc_hrmpayment(MAcctSchema[] ass, ResultSet rs, String trxName)
	{
		super (ass, Mhrmpayment.class, rs, null, trxName);
	}	//	Doc_Invoice

	/** Contained Optional Tax Lines    */
	private DocTax[]        m_taxes = null;
	/** Currency Precision				*/
	private int				m_precision = -1;

	/**
	 *  Load Specific Document Details
	 *  @return error message or null
	 */
	protected String loadDocumentDetails ()
	{
		
		Mhrmpayment hr = (Mhrmpayment)getPO();
		setDateDoc(hr.getDateAcct());
//		setDateDoc(invoice.getDateInvoiced());
//		setIsTaxIncluded(invoice.isTaxIncluded());
//		//	Amounts
//		setAmount(Doc.AMTTYPE_Gross, invoice.getGrandTotal());
//		setAmount(Doc.AMTTYPE_Net, invoice.getTotalLines());
//		setAmount(Doc.AMTTYPE_Charge, invoice.getChargeAmt());
//				
//		//	Contained Objects
//		m_taxes = loadTaxes();
////		p_lines = loadLines(invoice);
//		log.fine("Lines=" + p_lines.length + ", Taxes=" + m_taxes.length);
		return null;
	}   //  loadDocumentDetails

	/**
	 *	Load Invoice Taxes
	 *  @return DocTax Array
	 */
	private DocTax[] loadTaxes()
	{
		ArrayList<DocTax> list = new ArrayList<DocTax>();
		String sql = "SELECT it.C_Tax_ID, t.Name, t.Rate, it.TaxBaseAmt, it.TaxAmt, t.IsSalesTax "
			+ "FROM C_Tax t, C_InvoiceTax it "
			+ "WHERE t.C_Tax_ID=it.C_Tax_ID AND it.C_Invoice_ID=?";
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try
		{
			pstmt = DB.prepareStatement(sql, getTrxName());
			pstmt.setInt(1, get_ID());
			rs = pstmt.executeQuery();
			//
			while (rs.next())
			{
				int C_Tax_ID = rs.getInt(1);
				String name = rs.getString(2);
				BigDecimal rate = rs.getBigDecimal(3);
				BigDecimal taxBaseAmt = rs.getBigDecimal(4);
				BigDecimal amount = rs.getBigDecimal(5);
				boolean salesTax = "Y".equals(rs.getString(6));
				//
				DocTax taxLine = new DocTax(C_Tax_ID, name, rate, 
					taxBaseAmt, amount, salesTax);
				log.fine(taxLine.toString());
				list.add(taxLine);
			}
		}
		catch (SQLException e)
		{
			log.log(Level.SEVERE, sql, e);
			return null;
		}
		finally {
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}

		//	Return Array
		DocTax[] tl = new DocTax[list.size()];
		list.toArray(tl);
		return tl;
	}//	loadTaxes

	/**
	 *	Load Invoice Line
	 *	@param invoice invoice
	 *  @return DocLine Array
	 */
	private DocLine[] loadLines (Mhrmpayment invoice)
	{
		ArrayList<DocLine> list = new ArrayList<DocLine>();
//		//
//		MInvoiceLine[] lines = invoice.getLines(false);
//		for (int i = 0; i < lines.length; i++)
//		{
//			MInvoiceLine line = lines[i];
//			if (line.isDescription())
//				continue;
//			DocLine docLine = new DocLine(line, this);
//			//	Qty
//			BigDecimal Qty = line.getQtyInvoiced();
//			boolean cm = getDocumentType().equals(DOCTYPE_ARCredit) 
//				|| getDocumentType().equals(DOCTYPE_APCredit);
//			docLine.setQty(cm ? Qty.negate() : Qty, invoice.isSOTrx());
//			//
//			BigDecimal LineNetAmt = line.getLineNetAmt();
//			BigDecimal PriceList = line.getPriceList();
//			int C_Tax_ID = docLine.getC_Tax_ID();
//			//	Correct included Tax
//			if (isTaxIncluded() && C_Tax_ID != 0 && !getDocumentType().equals(DOCTYPE_AdvanceStatement))
//			{
//				MTax tax = MTax.get(getCtx(), C_Tax_ID);
//				if (!tax.isZeroTax())
//				{
//					BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, getStdPrecision());
//					log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax);
//					LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
//					for (int t = 0; t < m_taxes.length; t++)
//					{
//						if (m_taxes[t].getC_Tax_ID() == C_Tax_ID)
//						{
//							m_taxes[t].addIncludedTax(LineNetAmtTax);
//							break;
//						}
//					}
//					BigDecimal PriceListTax = tax.calculateTax(PriceList, true, getStdPrecision());
//					PriceList = PriceList.subtract(PriceListTax);
//				}
//			}	//	correct included Tax
//			
//			docLine.setAmount (LineNetAmt, PriceList, Qty);	//	qty for discount calc
//			if (docLine.isItem())
//				m_allLinesService = false;
//			else
//				m_allLinesItem = false;
//			//
//			log.fine(docLine.toString());
//			list.add(docLine);
//		}
//		
//		//	Convert to Array
		DocLine[] dls = new DocLine[list.size()];
//		list.toArray(dls);
//
//		//	Included Tax - make sure that no difference
//		if (isTaxIncluded())
//		{
//			for (int i = 0; i < m_taxes.length; i++)
//			{
//				if (m_taxes[i].isIncludedTaxDifference())
//				{
//					BigDecimal diff = m_taxes[i].getIncludedTaxDifference(); 
//					for (int j = 0; j < dls.length; j++)
//					{
//						if (dls[j].getC_Tax_ID() == m_taxes[i].getC_Tax_ID())
//						{
//							dls[j].setLineNetAmtDifference(diff);
//							break;
//						}
//					}	//	for all lines
//				}	//	tax difference
//			}	//	for all taxes
//		}	//	Included Tax difference
//		
		//	Return Array
		return dls;
	}	//	loadLines

	/**
	 * 	Get Currency Precision
	 *	@return precision
	 */
	private int getStdPrecision()
	{
		if (m_precision == -1)
			m_precision = MCurrency.getStdPrecision(getCtx(), getC_Currency_ID());
		return m_precision;
	}	//	getPrecision

	
	/**************************************************************************
	 *  Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
	 *  @return positive amount, if total invoice is bigger than lines
	 */
	public BigDecimal getBalance()
	{
		BigDecimal retValue = Env.ZERO;
		
		return retValue;
	}   //  getBalance

	/**
	 *  Create Facts (the accounting logic) for
	 *  ARI, ARC, ARF, API, APC.
	 *  <pre>
	 *  ARI, ARF
	 *      Receivables     DR
	 *      Charge                  CR
	 *      TaxDue                  CR
	 *      Revenue                 CR
	 *
	 *  ARC
	 *      Receivables             CR
	 *      Charge          DR
	 *      TaxDue          DR
	 *      Revenue         RR
	 *
	 *  API
	 *      Payables                CR
	 *      Charge          DR
	 *      TaxCredit       DR
	 *      Expense         DR
	 *
	 *  APC
	 *      Payables        DR
	 *      Charge                  CR
	 *      TaxCredit               CR
	 *      Expense                 CR
	 *  </pre>
	 *  @param as accounting schema
	 *  @return Fact
	 */
	public ArrayList<Fact> createFacts (MAcctSchema as)
	{
		//
		ArrayList<Fact> facts = new ArrayList<Fact>();
		//  create Fact Header
		
		//MAccount acct = null;
		MAccount acct7210 = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as); //7210
		MAccount acct3120 = getAccount(Doc.ACCTTYPE_HRMIPN, as);	//3120
		MAccount acct3150 = getAccount(Doc.ACCTTYPE_HRMCNALOG, as);	//3150
		MAccount acct3210 = getAccount(Doc.ACCTTYPE_HRMCOTCH, as);	//3210
		MAccount acct3220 = getAccount(Doc.ACCTTYPE_HRMOPV, as);	//3220
		MAccount acct3350 = getAccount(Doc.ACCTTYPE_HRMSalary, as);	//3350
		MAccount acct3430 = getAccount(Doc.ACCTTYPE_HRMREZERV, as); //3430
		
		Fact fact = new Fact(this, as, Fact.POST_Actual);
		Mhrmpayment hrmpayment = (Mhrmpayment)getPO();
		
		if (hrmpayment.haveCorrectDocument()) {
			makeCorrectGLJournal(hrmpayment, as);
			facts = makeCorrectFact(hrmpayment, as);
			return facts;
		}
		
		String sql = " select hrm_payment_list_id from adempiere.hrm_payment_list where hrm_payment_ID = " + hrmpayment.gethrm_payment_ID();
		
		List<Mhrmpaymentlist> lines = new ArrayList<Mhrmpaymentlist>();
		Mhrmpaymentlist line;
		
		PreparedStatement pstmt = null;
		ResultSet rs = null;
			
		pstmt = null;
		rs = null;
		try{
			pstmt = DB.prepareStatement(sql, null);
			rs = pstmt.executeQuery();
			while (rs.next()) {
				line = new Mhrmpaymentlist(Env.getCtx(), rs.getInt(1), null);
				lines.add(line);
			}
		}catch(SQLException e){
			log.log(Level.WARNING, e.getLocalizedMessage());
		}
		finally
		{
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}	
		
		class hrm_salarysum_v{
			BigDecimal opv = new BigDecimal(0);
			BigDecimal ipn = new BigDecimal(0);
			BigDecimal salary = new BigDecimal(0);
			BigDecimal cotch =  new BigDecimal(0);
			BigDecimal cnalog =  new BigDecimal(0);
			BigDecimal amount =  new BigDecimal(0);
			BigDecimal vacation =  new BigDecimal(0);
			BigDecimal aidvacation =  new BigDecimal(0);
			BigDecimal medicare_total = new BigDecimal(0);
			BigDecimal medicare = new BigDecimal(0);
			BigDecimal loan = new BigDecimal(0);
			BigDecimal checkoff = new BigDecimal(0);
			BigDecimal btrip = new BigDecimal(0);
			BigDecimal review = new BigDecimal(0);
			BigDecimal bonus = new BigDecimal(0);
			BigDecimal maid = new BigDecimal(0);
			BigDecimal maidoff = new BigDecimal(0);
			BigDecimal profit = new BigDecimal(0);
			BigDecimal profit_amount = new BigDecimal(0);
			BigDecimal btriptax = new BigDecimal(0);

			public BigDecimal getAmount() {
				return amount;
			}
			public void setAmount(BigDecimal amount) {
				this.amount = amount;
			}
			public BigDecimal getCotch() {
				return cotch;
			}
			public void setCotch(BigDecimal cotch) {
				this.cotch = cotch;
			}
			public BigDecimal getCnalog() {
				return cnalog;
			}
			public void setCnalog(BigDecimal cnalog) {
				this.cnalog = cnalog;
			}
			int C_BPartner_ID = 0;
			public int getC_BPartner_ID() {
				return C_BPartner_ID;
			}
			public void setC_BPartner_ID(int c_BPartner_ID) {
				C_BPartner_ID = c_BPartner_ID;
			}
			public BigDecimal getOpv() {
				return opv;
			}
			public void setOpv(BigDecimal opv) {
				this.opv = opv;
			}
			public BigDecimal getIpn() {
				return ipn;
			}
			public void setIpn(BigDecimal ipn) {
				this.ipn = ipn;
			}
			public BigDecimal getSalary() {
				return salary;
			}
			public void setSalary(BigDecimal salary) {
				this.salary = salary;
			}
			public BigDecimal getVacation() {
				return vacation;
			}
			public void setVacation(BigDecimal vacation) {
				this.vacation = vacation;
			}
			public BigDecimal getAidvacation() {
				return aidvacation;
			}
			public void setAidvacation(BigDecimal aidvacation) {
				this.aidvacation = aidvacation;
			}			
			public BigDecimal getMedicare_total() {
				return medicare_total;
			}
			public void setMedicare_total(BigDecimal medicare_total) {
				this.medicare_total = medicare_total;
			}
			public BigDecimal getMedicare() {
				return medicare;
			}
			public void setMedicare(BigDecimal medicare) {
				this.medicare = medicare;
			}
			public BigDecimal getLoan() {
				return loan;
			}
			public void setLoan(BigDecimal loan) {
				this.loan = loan;
			}
			public BigDecimal getCheckoff() {
				return checkoff;
			}
			public void setCheckoff(BigDecimal checkoff) {
				this.checkoff = checkoff;
			}
			public BigDecimal getBtrip() {
				return btrip;
			}
			public void setBtrip(BigDecimal btrip) {
				this.btrip = btrip;
			}			
			public BigDecimal getReview() {
				return review;
			}
			public void setReview(BigDecimal review) {
				this.review = review;
			}			
			public BigDecimal getBonus() {
				return bonus;
			}
			public void setBonus(BigDecimal bonus) {
				this.bonus = bonus;
			}
			public BigDecimal getMaid() {
				return maid;
			}
			public void setMaid(BigDecimal maid) {
				this.maid = maid;
			}
			public BigDecimal getMaidoff() {
				return maidoff;
			}
			public void setMaidoff(BigDecimal maidoff) {
				this.maidoff = maidoff;
			}
			public BigDecimal getProfit() {
				return profit;
			}
			public void setProfit(BigDecimal profit) {
				this.profit = profit;
			}
			public BigDecimal getProfit_amount() {
				return profit_amount;
			}
			public void setProfit_amount(BigDecimal profit_amount) {
				this.profit_amount = profit_amount;
			}
			public BigDecimal getBtriptax() {
				return btriptax;
			}
			public void setBtriptax(BigDecimal btriptax) {
				this.btriptax = btriptax;
			}
						
		}
		
		List<hrm_salarysum_v> listOfHrmSalary = new ArrayList<hrm_salarysum_v>();
		
		for(Mhrmpaymentlist l: lines){
			sql = " select * from hrm_salarysum_v where hrm_payment_list_id = " + l.gethrm_payment_list_ID();
			
			pstmt = null;
			rs = null;
				
			try{
				pstmt = DB.prepareStatement(sql, null);
				rs = pstmt.executeQuery();
				while (rs.next()) {
					hrm_salarysum_v ll = new hrm_salarysum_v();
					ll.setIpn(rs.getBigDecimal("ipn"));
					ll.setOpv(rs.getBigDecimal("opv"));
					ll.setSalary(rs.getBigDecimal("totalsum"));
					ll.setCnalog(rs.getBigDecimal("cnalog"));
					ll.setCotch(rs.getBigDecimal("cotch"));
					ll.setC_BPartner_ID(l.getC_BPartner_ID());					
					ll.setAmount(rs.getBigDecimal("amount"));
					ll.setVacation(rs.getBigDecimal("vacation"));
					ll.setAidvacation(rs.getBigDecimal("aidvacation"));
					ll.setMedicare_total(rs.getBigDecimal("medicare"));
					ll.setMedicare(rs.getBigDecimal("medicare_amount"));
					ll.setLoan(rs.getBigDecimal("loan"));
					ll.setCheckoff(rs.getBigDecimal("checkoff"));
					ll.setBtrip(rs.getBigDecimal("btrip"));
					ll.setReview(rs.getBigDecimal("review"));
					ll.setBonus(rs.getBigDecimal("bonus"));
					ll.setMaid(rs.getBigDecimal("materialaid"));
					ll.setMaidoff(rs.getBigDecimal("materialaidtaxoff"));
					ll.setProfit(rs.getBigDecimal("profit"));
					ll.setProfit_amount(rs.getBigDecimal("profit_amount"));
					ll.setBtriptax(rs.getBigDecimal("btriptax"));
					listOfHrmSalary.add(ll);
				}
			}catch(SQLException e){
				log.log(Level.WARNING, e.getLocalizedMessage());
			}
			finally
			{
				DB.close(rs, pstmt);
				rs = null; pstmt = null;
			}
		}
		
		FactLine fl = null;
		setDateAcct(hrmpayment.getDateFrom());
		
		DocLine DocLine = null;
		for(hrm_salarysum_v l: listOfHrmSalary){
			int C_BPartner_ID = l.getC_BPartner_ID();
			//Salary
			BigDecimal salary = l.getSalary();
			salary = salary.add(l.getVacation().negate());
			salary = salary.add(l.getAidvacation().negate());
			salary = salary.add(l.getReview().negate());
			salary = salary.add(l.getBonus().negate());
			salary = salary.add(l.getMedicare_total().negate());
			salary = salary.add(l.getMaid().negate());
			salary = salary.add(l.getMaidoff().negate());
			salary = salary.add(l.getProfit().negate());	
			
			// detect c_charge_id and fill hrm_paymentline
			int C_Charge_ID = 1000048;
			Mhrmpaymentline charge = Mhrmpaymentline.getline(hrmpayment.gethrm_payment_ID(), C_BPartner_ID, C_Charge_ID);
			if (charge == null || charge.get_ID() == 0){
				charge = new Mhrmpaymentline(getCtx(), 0, null);
			}
			charge.sethrm_payment_ID(hrmpayment.gethrm_payment_ID());
			charge.setC_Charge_ID(C_Charge_ID);
			charge.setC_BPartner_ID(C_BPartner_ID);
			charge.saveEx();
			DocLine = new DocLine(charge, this);
			//DR
			//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);
			setC_BPartner_ID(C_BPartner_ID);						
			fl = fact.createLine(DocLine, acct7210, getC_Currency_ID(), salary, null);
			
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			//CR
			//acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(DocLine, acct3350, getC_Currency_ID(), null, salary);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			// Medicare total
			BigDecimal medicare_total = l.getMedicare_total();
			
			//DR
			//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);
			setC_BPartner_ID(C_BPartner_ID);						
			fl = fact.createLine(DocLine, acct7210, getC_Currency_ID(), medicare_total, null);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			//CR
			//acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(DocLine, acct3350, getC_Currency_ID(), null, medicare_total);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			// Medicare
			BigDecimal medicare = l.getMedicare();
			
			//DR
			//acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null, acct3350, getC_Currency_ID(), medicare, null);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			//CR
			//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null,acct7210,getC_Currency_ID(), null, medicare);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			
			////
			// Profit total
			BigDecimal profit_total = l.getProfit();
			
			//DR
			setC_BPartner_ID(C_BPartner_ID);						
			fl = fact.createLine(DocLine, acct7210, getC_Currency_ID(), profit_total, null);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			//CR
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(DocLine, acct3350, getC_Currency_ID(), null, profit_total);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			// Profit
			BigDecimal profit = l.getProfit_amount();
			
			//DR
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null, acct3350, getC_Currency_ID(), profit, null);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			//CR
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null,acct7210,getC_Currency_ID(), null, profit);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			// Compensation
			BigDecimal compens = l.getBtrip().add(l.getBtriptax().negate());
			
			//DR
			setC_BPartner_ID(C_BPartner_ID);						
			fl = fact.createLine(DocLine, acct7210, getC_Currency_ID(), compens, null);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			//CR
			setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(DocLine, acct3350, getC_Currency_ID(), null, compens);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			
			
			////
			
			// Loan
		/*	BigDecimal loan = l.getLoan();			
			//DR
			acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
			acct.setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null, acct,	getC_Currency_ID(), loan, null);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			//CR
			acct = getAccount(Doc.ACCTTYPE_Loan, as);
			acct.setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null,acct,getC_Currency_ID(), null, loan);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());

			// CheckOff TODO убрать когда реализуем удержание
			BigDecimal checkoff = l.getCheckoff();
			//DR
			acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
			acct.setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null, acct,	getC_Currency_ID(), checkoff, null);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
			//CR
			acct = getAccount(Doc.ACCTTYPE_CheckOff, as);
			acct.setC_BPartner_ID(C_BPartner_ID);
			fl = fact.createLine(null,acct,getC_Currency_ID(), null, checkoff);
			if(fl != null)
				fl.setDateAcct(hrmpayment.getDateFrom());
*/
			//IPN
			BigDecimal ipn = l.getIpn();
			BigDecimal ipnSaldo = getSaldo(getAccount(Doc.ACCTTYPE_HRMIPN, as).getAccount_ID(),C_BPartner_ID,hrmpayment.getDateFrom());
			ipn = ipn.add(ipnSaldo.negate());
				//DR
				//acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
				setC_BPartner_ID(C_BPartner_ID);
				fl = fact.createLine(null, acct3350, getC_Currency_ID(), ipn, null);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());				
				//CR
				//acct = getAccount(Doc.ACCTTYPE_HRMIPN, as);
				setC_BPartner_ID(C_BPartner_ID);
				fl = fact.createLine(null, acct3120, getC_Currency_ID(), null, ipn);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());
				
			//OPV
			BigDecimal opv = l.getOpv();
			BigDecimal opvSaldo = getSaldo(getAccount(Doc.ACCTTYPE_HRMOPV, as).getAccount_ID(),C_BPartner_ID,hrmpayment.getDateFrom());
			opv = opv.add(opvSaldo.negate());
				//DR
				//acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
				setC_BPartner_ID(C_BPartner_ID);
				fl = fact.createLine(null, acct3350, getC_Currency_ID(), opv, null);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());
				//CR
				//acct = getAccount(Doc.ACCTTYPE_HRMOPV, as);
				setC_BPartner_ID(C_BPartner_ID);
				fl = fact.createLine(null, acct3220, getC_Currency_ID(), null, opv);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());
				
			//COTCH
			BigDecimal cotch = l.getCotch();
			BigDecimal cotchSaldo = getSaldo(acct3210.getAccount_ID(),C_BPartner_ID,hrmpayment.getDateFrom());
			cotch = cotch.add(cotchSaldo.negate());
			
			// detect c_charge_id and fill hrm_paymentline
			C_Charge_ID = 1000049;
				charge = Mhrmpaymentline.getline(hrmpayment.gethrm_payment_ID(), C_BPartner_ID, C_Charge_ID);
				if (charge == null || charge.get_ID() == 0){
					charge = new Mhrmpaymentline(getCtx(), 0, null);
				}
				charge.sethrm_payment_ID(hrmpayment.gethrm_payment_ID());
				charge.setC_Charge_ID(C_Charge_ID);
				charge.setC_BPartner_ID(C_BPartner_ID);
				charge.saveEx();
				DocLine = new DocLine(charge, this);
				//DR
				//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);
				setC_BPartner_ID(C_BPartner_ID);				
				fl = fact.createLine(DocLine,acct7210,getC_Currency_ID(), cotch, null);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());
				//CR
				//acct = getAccount(Doc.ACCTTYPE_HRMCOTCH, as);
				setC_BPartner_ID(C_BPartner_ID);
				fl = fact.createLine(DocLine, acct3210,	getC_Currency_ID(), null, cotch);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());
				
			//CNALOG
			BigDecimal cnalog = l.getCnalog();
			BigDecimal cnalogSaldo = getSaldo(acct3150.getAccount_ID(),C_BPartner_ID,hrmpayment.getDateFrom());
			cnalog = cnalog.add(cnalogSaldo.negate());
			// detect c_charge_id and fill hrm_paymentline
				C_Charge_ID = 1000051;
				charge = Mhrmpaymentline.getline(hrmpayment.gethrm_payment_ID(), C_BPartner_ID, C_Charge_ID);
				if (charge == null || charge.get_ID() == 0){
					charge = new Mhrmpaymentline(getCtx(), 0, null);
				}
				charge.sethrm_payment_ID(hrmpayment.gethrm_payment_ID());
				charge.setC_Charge_ID(C_Charge_ID);
				charge.setC_BPartner_ID(C_BPartner_ID);
				charge.saveEx();
				DocLine = new DocLine(charge, this);
				//DR
				//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);
				setC_BPartner_ID(C_BPartner_ID);
				fl = fact.createLine(DocLine,acct7210,getC_Currency_ID(), cnalog, null);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());
				//CR
				//acct = getAccount(Doc.ACCTTYPE_HRMCNALOG, as);
				setC_BPartner_ID(C_BPartner_ID);
				fl = fact.createLine(DocLine, acct3150,	getC_Currency_ID(), null, cnalog);
				if(fl != null)
					fl.setDateAcct(hrmpayment.getDateFrom());
				
		}
		
		int c_currency_id = 341;
		//int org = Env.getContextAsInt(getCtx(), "#AD_Org_ID");
		int reserveID = 110;
		int SecNachil = 100;
		int SecSOtch = 110;
		int SecSTax = 120;
		X_C_Period Period = Util.getPeriod(hrmpayment.getDateFrom());
		if (Period == null)
			throw new AdempiereException(" Not set period in table C_Period for this month ");
		
		//Reserve----------------------------------------------------------
		String sDocNum = "HR Резерв: " + hrmpayment.getName();
		
        sql="SELECT GL_JournalBatch_ID FROM GL_JournalBatch "
				+ " WHERE DocumentNo = "+ "'"+sDocNum+"'";
        int no = DB.getSQLValue(getTrxName(), sql.toString());
        if (no<0) no =0;
		
		MJournalBatch Batch = new MJournalBatch(getCtx(), no, null);
		Batch.setDocumentNo("HR Резерв: " + hrmpayment.getName());
		Batch.setDescription("HR: " + hrmpayment.getName());
		Batch.setC_DocType_ID(1000000);
		Batch.setDateDoc(hrmpayment.getDateAcct()); 
		Batch.setDateAcct(hrmpayment.getDateFrom());		
		Batch.setC_Period_ID(Period.getC_Period_ID());//get current period!
		Batch.setC_Currency_ID(c_currency_id);
		Batch.setAD_Org_ID(1000000);
		Batch.saveEx();

		sDocNum="HR: Резерв" + hrmpayment.getName();
		sql="SELECT GL_Journal_ID FROM GL_Journal "
		  	      + " WHERE DocumentNo = "+"'"+sDocNum+"'"
		  	      + " AND GL_JournalBatch_ID = "+Batch.get_ID();
		no = DB.getSQLValue(getTrxName(), sql.toString());
		if (no<0) no = 0;
		MJournal Journal=null;
		if (no>0) {
		 Journal = new MJournal (getCtx(), no, getTrxName());
	     MJournalLine[] JournalLine = Journal.getLines(true); 
			for(MJournalLine reversalLine:JournalLine  ) {
				reversalLine.deleteEx(true, getTrxName());
			}
		} else
		  Journal = new MJournal(Batch);
		Journal.setDocumentNo(sDocNum);
		Journal.setDescription("HR: " + hrmpayment.getName());
		Journal.setC_DocType_ID(1000000);
		Journal.setDateDoc(hrmpayment.getDateAcct());
		Journal.setDateAcct(hrmpayment.getDateFrom());
		Journal.setC_Period_ID(Period.getC_Period_ID());//get current period!
		Journal.setC_Currency_ID(c_currency_id);
		Journal.setC_AcctSchema_ID(1000000);
		Journal.setGL_Category_ID(1000000);
		Journal.setC_ConversionType_ID(1000001);
		Journal.saveEx();
		
		boolean holiDay = false;
		
		Timestamp dateFrom = hrmpayment.getDateFrom();
		DateTime dt = new DateTime(dateFrom.getTime());
		DateTime lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
		DateTime nextMonth = lastDayOfMonth.plusDays(1);
		dateFrom = new Timestamp(nextMonth.getMillis());
		
		for(hrm_salarysum_v l: listOfHrmSalary){
			
			int C_BPartner_ID = l.getC_BPartner_ID();
			
			X_HR_Employee hremp = X_HR_Employee.getHR_Employee(C_BPartner_ID, null);
			if (hremp.getC_BPartner_ID() == 0)
				throw new AdempiereException ("Info about employee was empty:" + C_BPartner_ID);
			
			if (hremp.getEndDate().after(dateFrom)){
				
				int lin = 10;			

				BigDecimal sum = new BigDecimal(0);
				sum = l.getAmount();
				
		    	if(sum != null && sum.compareTo(new BigDecimal(0)) == 1){
		    		holiDay = true;
		    		
		    		//new reserve -----------------------------------------------------------
			    	sum = sum.multiply(new BigDecimal(9.09).divide(new BigDecimal(100)));

			    	MJournalLine JournalLine = new MJournalLine(Journal); 
					JournalLine.setDescription(""+C_BPartner_ID);
					JournalLine.setC_Currency_ID(341);
					JournalLine.sethrm_reserve_ID(reserveID);
					JournalLine.sethrm_reservesectional_ID(SecNachil);
					JournalLine.setLine(lin);
					lin += 10;
					
					
					MAccountCombination AccCombination = new MAccountCombination(getCtx(), 0, null);
					//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);	//7210
					if(checkValidCombination(acct7210.get_ID(), C_BPartner_ID) == 0){
						 
						//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);	//7210					
						AccCombination.setAccount_ID(acct7210.getAccount_ID());
						AccCombination.setC_BPartner_ID(C_BPartner_ID);
						AccCombination.setCombination("HR: " + C_BPartner_ID);
						AccCombination.setC_AcctSchema_ID(as.getC_AcctSchema_ID()); // 1000000
						AccCombination.saveEx();
					}
					
					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
					JournalLine.setAmtSourceDr(sum.setScale(2, BigDecimal.ROUND_HALF_UP));
					JournalLine.setAmtSourceCr(new BigDecimal(0));
					
					JournalLine.saveEx();
					
					
			    	JournalLine = new MJournalLine(Journal); 
					JournalLine.setDescription(""+C_BPartner_ID);
					JournalLine.setC_Currency_ID(c_currency_id);
					JournalLine.sethrm_reserve_ID(reserveID);
					JournalLine.sethrm_reservesectional_ID(SecNachil);
					JournalLine.setLine(lin);
					lin += 10;
					
					AccCombination = new MAccountCombination(getCtx(), 0, null);
					//acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//7210
					if(checkValidCombination(acct3430.get_ID(), C_BPartner_ID) == 0){
						 
						//acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//7210
						
						AccCombination.setAccount_ID(acct3430.getAccount_ID());
						AccCombination.setC_BPartner_ID(C_BPartner_ID);
						AccCombination.setCombination("HR: " + C_BPartner_ID);
						AccCombination.setC_AcctSchema_ID(acct3430.getC_AcctSchema_ID()); //1000000
						AccCombination.saveEx();
					}
					
					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
					JournalLine.setAmtSourceDr(new BigDecimal(0));
					JournalLine.setAmtSourceCr(sum.setScale(2, BigDecimal.ROUND_HALF_UP));
					JournalLine.saveEx();				
					
					// соц. налог------------------------------------------------------				
					
					BigDecimal TaxRes = sum.multiply(new BigDecimal(5.40)).divide(new BigDecimal(100));

			    	JournalLine = new MJournalLine(Journal); 
					JournalLine.setDescription("" + C_BPartner_ID);
					JournalLine.setC_Currency_ID(c_currency_id);
					JournalLine.sethrm_reserve_ID(reserveID);
					JournalLine.sethrm_reservesectional_ID(SecSTax);
					JournalLine.setLine(lin);
					lin += 10;
					
					AccCombination = new MAccountCombination(getCtx(), 0, null);
					//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);	//3150
					if(checkValidCombination(acct7210.get_ID(), C_BPartner_ID) == 0){					 
					
						AccCombination.setAccount_ID(acct7210.getAccount_ID());
						AccCombination.setC_BPartner_ID(C_BPartner_ID);
						AccCombination.setCombination("HR: " + C_BPartner_ID);
						AccCombination.setC_AcctSchema_ID(acct7210.getC_AcctSchema_ID()); // 1000000
						AccCombination.saveEx();
					}
					
					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
					JournalLine.setAmtSourceDr(TaxRes.setScale(2, BigDecimal.ROUND_HALF_UP));
					JournalLine.setAmtSourceCr(new BigDecimal(0));
					JournalLine.saveEx();				
					
			    	JournalLine = new MJournalLine(Journal); 
					JournalLine.setDescription("" + C_BPartner_ID);
					JournalLine.setC_Currency_ID(c_currency_id);
					JournalLine.sethrm_reserve_ID(reserveID);
					JournalLine.sethrm_reservesectional_ID(SecSTax);
					JournalLine.setLine(lin);
					lin += 10;
					
					AccCombination = new MAccountCombination(getCtx(), 0, null);
					//acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
					if(checkValidCombination(acct3430.get_ID(), C_BPartner_ID) == 0){
					
						AccCombination.setAccount_ID(acct3430.getAccount_ID());
						AccCombination.setC_BPartner_ID(C_BPartner_ID);
						AccCombination.setCombination("HR: " + C_BPartner_ID);
						AccCombination.setC_AcctSchema_ID(acct3430.getC_AcctSchema_ID()); // 1000000
						AccCombination.saveEx();
					}
					
					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
					JournalLine.setAmtSourceDr(new BigDecimal(0));
					JournalLine.setAmtSourceCr(TaxRes.setScale(2, BigDecimal.ROUND_HALF_UP));
					
					JournalLine.saveEx();								
					
					//соц. отчисления-----------------------------------------------------------------------
					
					BigDecimal othcRes = sum.multiply(new BigDecimal(4.50)).divide(new BigDecimal(100));

			    	JournalLine = new MJournalLine(Journal); 
					JournalLine.setDescription("" + C_BPartner_ID);
					JournalLine.setC_Currency_ID(c_currency_id);
					JournalLine.sethrm_reserve_ID(reserveID);
					JournalLine.sethrm_reservesectional_ID(SecSOtch);
					JournalLine.setLine(lin);
					lin += 10;
					
					AccCombination = new MAccountCombination(getCtx(), 0, null);
					//acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);	//3210
					if(checkValidCombination(acct7210.get_ID(), C_BPartner_ID) == 0){
						
						AccCombination.setAccount_ID(acct7210.getAccount_ID());
						AccCombination.setC_BPartner_ID(C_BPartner_ID);
						AccCombination.setCombination("HR: " + C_BPartner_ID);
						AccCombination.setC_AcctSchema_ID(acct7210.getC_AcctSchema_ID()); // 1000000
						AccCombination.saveEx();
					}
					
					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
					JournalLine.setAmtSourceDr(othcRes.setScale(2, BigDecimal.ROUND_HALF_UP));
					JournalLine.setAmtSourceCr(new BigDecimal(0));
					JournalLine.saveEx();					
					
					JournalLine = new MJournalLine(Journal); 
					JournalLine.setDescription("" + C_BPartner_ID);
					JournalLine.setC_Currency_ID(c_currency_id);
					JournalLine.sethrm_reserve_ID(reserveID);
					JournalLine.sethrm_reservesectional_ID(SecSOtch);
					JournalLine.setLine(lin);
					lin += 10;
					
					AccCombination = new MAccountCombination(getCtx(), 0, null);
					//acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
					if(checkValidCombination(acct3430.get_ID(), C_BPartner_ID) == 0){
						 					
						AccCombination.setAccount_ID(acct3430.getAccount_ID());
						AccCombination.setC_BPartner_ID(C_BPartner_ID);
						AccCombination.setCombination("HR: " + C_BPartner_ID);
						AccCombination.setC_AcctSchema_ID(acct3430.getC_AcctSchema_ID());
						AccCombination.saveEx();
					}
					
					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
					JournalLine.setAmtSourceDr(new BigDecimal(0));
					JournalLine.setAmtSourceCr(othcRes.setScale(2, BigDecimal.ROUND_HALF_UP));
					
					JournalLine.saveEx();
					
		    	}		
			}
			
			//if(!holiDay)
			//	Batch.delete(true);

			
			}
			
		
//		//vacation----------------------------------------------------------
//
//		Batch = new MJournalBatch(getCtx(), 0, null);
//		Batch.setDocumentNo("HR Отпуск: " + hrmpayment.getName());
//		Batch.setDescription("HR: " + hrmpayment.getName());
//		Batch.setC_DocType_ID(1000000);
//		Batch.setDateDoc(hrmpayment.getDateAcct()); 
//		Batch.setDateAcct(hrmpayment.getDateAcct());
//		Batch.setC_Period_ID(1000011);//get current period!
//		Batch.setC_Currency_ID(341);
//		Batch.setAD_Org_ID(1000000);
//		Batch.saveEx();
//		
//		Journal = new MJournal(Batch);
//		Journal.setDocumentNo("HR: Отпуск" + hrmpayment.getName());
//		Journal.setDescription("HR: " + hrmpayment.getName());
//		Journal.setC_DocType_ID(1000000);
//		Journal.setDateDoc(hrmpayment.getDateAcct());
//		Journal.setDateAcct(hrmpayment.getDateAcct());
//		Journal.setC_Period_ID(1000011);//get current period!
//		Journal.setC_Currency_ID(341);
//		Journal.setC_AcctSchema_ID(1000000);
//		Journal.setGL_Category_ID(1000000);
//		Journal.setC_ConversionType_ID(1000001);
//		Journal.saveEx();		
//		
//		
//		boolean vacationb = false;
//		
//		for(hrm_salarysum_v l: listOfHrmSalary){
//			int lin = 10;
//			int C_BPartner_ID = l.getC_BPartner_ID();
//			
//			Mhrmvacationline vacation = Mhrmvacationline.getVacationline(C_BPartner_ID, hrmpayment.getDateFrom());
//			BigDecimal amountVacancy = vacation.gethrm_amountvacation();
//			
//			Mhrmlimitholiday holiDaylimit = null;
//		    holiDaylimit = Mhrmlimitholiday.getLimitHoliday(C_BPartner_ID,true);
//		    
//	    	if(holiDaylimit != null && vacation != null){
//	    		vacationb = true;
//	    		
//	    		MJournalLine JournalLine = null;
////		    	//списано
////					//DR
////					acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
////					acct.setC_BPartner_ID(C_BPartner_ID);
////					fact.createLine(null,acct,getC_Currency_ID(), reserve, null);
////					//CR
////					acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);			//3350
////					acct.setC_BPartner_ID(C_BPartner_ID);
////					fact.createLine(null, acct,	getC_Currency_ID(), null, reserve);	    		
//	    		//reserve -----------------------------------------------------------
//	    		BigDecimal reserve = new BigDecimal(0);
//		    	reserve = holiDaylimit.gethrm_holidayreserve();
//		    	
//		    	//1. если сумма резерва больше 0 и не больше суммы отпуска то списываем все и занимаем сумму у предприятия с которых также снимаем налог
//		    	if(reserve.compareTo(new BigDecimal(0)) == 1 && reserve.compareTo(amountVacancy) == -1){
//		    		//1.1 СПИСЫВАЕМ
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					MAccountCombination AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						int s = acct.getAccount_ID();
//						
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(reserve);
//					JournalLine.setAmtSourceCr(new BigDecimal(0));
//					JournalLine.saveEx();
//				
//					//---------------------------------------
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);	//3350
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						int s = acct.getAccount_ID();
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(new BigDecimal(0));
//					JournalLine.setAmtSourceCr(reserve);
//					JournalLine.saveEx();
//					
//					//1.2. ЗАНИМАЕМ 
//					BigDecimal credit = amountVacancy.subtract(reserve);
//					
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.sethrm_reservesectional_ID(SecNachil);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);	//7210
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						int s = acct.getAccount_ID();
//						
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(credit);
//					JournalLine.setAmtSourceCr(new BigDecimal(0));
//					JournalLine.saveEx();
//					
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.sethrm_reservesectional_ID(SecNachil);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);	//3350
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						int s = acct.getAccount_ID();
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(new BigDecimal(0));
//					JournalLine.setAmtSourceCr(credit);
//					JournalLine.saveEx();
//					
//					// 1.3. СНИМАЕМ НАЛОГИ С ТОГО ЧТО ЗАНЯЛИ
//					// 1.3.1. соц. налог------------------------------------------------------
//					
//					double TaxRes_ = credit.doubleValue();
//					TaxRes_ = TaxRes_ * 5.40 / 100;
//					BigDecimal TaxRes = credit.multiply(new BigDecimal(5.40)).divide(new BigDecimal(100));
//
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.sethrm_reservesectional_ID(SecSTax);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						 
//						int s = acct.getAccount_ID();
//						
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(TaxRes);
//					JournalLine.setAmtSourceCr(new BigDecimal(0));
//					
//					JournalLine.saveEx();
//					
//					
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.sethrm_reservesectional_ID(SecSTax);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMCNALOG, as);	//3150
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						 
//						int s = acct.getAccount_ID();
//						
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(new BigDecimal(0));
//					JournalLine.setAmtSourceCr(TaxRes);
//					JournalLine.saveEx();	
//					
//					//соц. отчисления-----------------------------------------------------------------------
//					BigDecimal othcRes = credit.multiply(new BigDecimal(4.50)).divide(new BigDecimal(100));
//
//					JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.sethrm_reservesectional_ID(SecSOtch);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						 
//						int s = acct.getAccount_ID();
//						
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(othcRes);
//					JournalLine.setAmtSourceCr(new BigDecimal(0));
//					
//					JournalLine.saveEx();
//					
//					
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.sethrm_reservesectional_ID(SecNachil);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMCOTCH, as);	
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						 
//						int s = acct.getAccount_ID();
//						
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(new BigDecimal(0));
//					JournalLine.setAmtSourceCr(othcRes);
//					JournalLine.saveEx();					
//					
//		    	}
//
//		    	
//		    	
//		    	//если сумма резерва больше 0 и больше суммы отпуска то списываем только необходимую сумму отпуска со счета резерва
//		    	if(reserve.compareTo(new BigDecimal(0)) == 1 && reserve.compareTo(amountVacancy) == 1){
//
//		    		BigDecimal diff = reserve.subtract(amountVacancy); 
//		    				
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					MAccountCombination AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						int s = acct.getAccount_ID();
//						
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(diff);
//					JournalLine.setAmtSourceCr(new BigDecimal(0));
//					JournalLine.saveEx();
//				
//					//---------------------------------------
//			    	JournalLine = new MJournalLine(Journal); 
//					JournalLine.setDescription(""+C_BPartner_ID);
//					JournalLine.setC_Currency_ID(341);
//					JournalLine.setLine(lin);
//					lin += 10;
//					
//					AccCombination = new MAccountCombination(getCtx(), 0, null);
//					acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);	//3350
//					if(checkValidCombination(acct.get_ID(), C_BPartner_ID) == 0){
//						int s = acct.getAccount_ID();
//						AccCombination.setAccount_ID(s);
//						AccCombination.setC_BPartner_ID(C_BPartner_ID);
//						AccCombination.setCombination("HR: " + C_BPartner_ID);
//						AccCombination.setC_AcctSchema_ID(1000000);
//						AccCombination.saveEx();
//					}
//					
//					JournalLine.setC_ValidCombination_ID(AccCombination.get_ID());
//					JournalLine.setAmtSourceDr(new BigDecimal(0));
//					JournalLine.setAmtSourceCr(diff);
//					JournalLine.saveEx();				
//		    	}		    	
//		    	
//		    	
//	    	}
//
//		}		
//		
//		if(!vacationb)
//			Batch.delete(true);
		
////	Mhrmlimitholiday holiDaylimit = Mhrmlimitholiday.getLimitHoliday(b.getC_BPartner_ID(),true);
//	Mhrmvacationline vacation = Mhrmvacationline.getVacationline(C_BPartner_ID, hrmpayment.getDateFrom());
//	
//    if(vacation != null){
//
//    	BigDecimal amountVacancy = null;
//	    BigDecimal reserve = null;
//    	
//	    Mhrmlimitholiday holiDaylimit = null;
//	    holiDaylimit = Mhrmlimitholiday.getLimitHoliday(C_BPartner_ID,true);
//    	if(holiDaylimit != null){
//    		
//	    	amountVacancy = vacation.gethrm_amountvacation();
//	    	reserve = holiDaylimit.gethrm_holidayreserve();
//	    	
//	    	//начисленно
//				//DR
//				acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);	//7210
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null,acct,getC_Currency_ID(), reserve, null);
//				//CR
//				acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);			//3430
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null, acct,	getC_Currency_ID(), null, reserve);				    	
//
//	    	//списано
//				//DR
//				acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null,acct,getC_Currency_ID(), reserve, null);
//				//CR
//				acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);			//3350
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null, acct,	getC_Currency_ID(), null, reserve);
//				
////			//соц. налог
//				double TaxRes_ = reserve.doubleValue();
//				TaxRes_ = TaxRes_ * 5.40 / 100;
//				BigDecimal TaxRes = reserve.multiply(new BigDecimal(5.40)).divide(new BigDecimal(100));
//				//DR
//				acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//3430
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null,acct,getC_Currency_ID(), TaxRes, null);
//				//CR
//				acct = getAccount(Doc.ACCTTYPE_HRMCNALOG, as);			//3150
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null, acct,	getC_Currency_ID(), null, TaxRes);
////				
////				
////			//соц. отчисления
//				BigDecimal othcRes = reserve.multiply(new BigDecimal(4.50)).divide(new BigDecimal(100));
//				//DR
//				acct = getAccount(Doc.ACCTTYPE_HRMREZERV, as);	//7210
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null,acct,getC_Currency_ID(), othcRes, null);
//				//CR
//				acct = getAccount(Doc.ACCTTYPE_HRMOPV, as);			//3430
//				acct.setC_BPartner_ID(C_BPartner_ID);
//				fact.createLine(null, acct,	getC_Currency_ID(), null, othcRes);
//				
//				
//			//разница	
//				BigDecimal diff = amountVacancy.subtract(reserve);
//				if(diff.compareTo(new BigDecimal(0)) == 1)
//				{
//					//DR
//					acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);	//7210
//					acct.setC_BPartner_ID(C_BPartner_ID);
//					fact.createLine(null,acct,getC_Currency_ID(), diff, null);
//					//CR
//					acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);			//3350
//					acct.setC_BPartner_ID(C_BPartner_ID);
//					fact.createLine(null, acct,	getC_Currency_ID(), null, diff);
//				}
//				
//    	}
//    }		
		
		
		
		
//		for(Mhrmpaymentlist l: lines){
//			//Salary
//			BigDecimal hrm_amountsalary = l.gethrm_amountsalary();
//				//DR
//				acct = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as);
//				fact.createLine(null,acct,getC_Currency_ID(), hrm_amountsalary, null);
//				//CR
//				acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
//				fact.createLine(null, acct,	getC_Currency_ID(), null, hrm_amountsalary);
//	
//			//IPN
//			BigDecimal hrm_ipn = l.gethrm_IPN();
//				//DR
//				acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
//				fact.createLine(null,acct,getC_Currency_ID(), hrm_ipn, null);
//				//CR
//				acct = getAccount(Doc.ACCTTYPE_HRMIPN, as);
//				fact.createLine(null, acct,	getC_Currency_ID(), null, hrm_ipn);
//			
//			//OPV
//			BigDecimal hrm_opv = l.gethrm_OPV();
//				//DR
//				acct = getAccount(Doc.ACCTTYPE_HRMSalary, as);
//				fact.createLine(null,acct,getC_Currency_ID(), hrm_opv, null);
//				//CR
//				acct = getAccount(Doc.ACCTTYPE_HRMOPV, as);
//				fact.createLine(null, acct,	getC_Currency_ID(), null, hrm_opv);
//		}

		facts.add(fact);
		return facts;
	}   //  createFact
	
	/**
	 * @param hrmpayment
	 * @param as
	 */
	private void makeCorrectGLJournal(Mhrmpayment hrmpayment, MAcctSchema as) {
		Mhrmpayment reversalDoc = new Mhrmpayment(Env.getCtx(),hrmpayment.getReversal_ID(),hrmpayment.get_TrxName());
		
		MJournalBatch reversalBatch = getBatch(reversalDoc);
		if (reversalBatch == null) {
			return;
		}
		
		MJournalBatch Batch = getBatch(hrmpayment);
		if (Batch != null) {
			return; //TODO Если есть запись в главном журнале что делать?
		}
		X_C_Period Period = Util.getPeriod(hrmpayment.getDateFrom());
		
		String batchNo = "HR Резерв: " + hrmpayment.getName(); 
		
		Batch = new MJournalBatch(getCtx(),0,hrmpayment.get_TrxName());
		Batch.setAD_Org_ID(reversalBatch.getAD_Org_ID());
		Batch.setDocumentNo(batchNo);
		Batch.setDescription("{->" + reversalBatch.getDocumentNo() + ")");
		Batch.setC_DocType_ID(1000000);
		Batch.setDateDoc(hrmpayment.getDateAcct()); 
		Batch.setDateAcct(hrmpayment.getDateFrom());		
		Batch.setC_Period_ID(Period.getC_Period_ID());//get current period!
		Batch.setC_Currency_ID(reversalBatch.getC_Currency_ID());
		Batch.setAD_Org_ID(1000000);
		Batch.setReversal_ID(reversalBatch.getGL_JournalBatch_ID());
//		Batch.setDocStatus(MJournalBatch.DOCSTATUS_Drafted );
//		Batch.setDocAction(MJournalBatch.DOCACTION_Complete);
//		Batch.setProcessing(false);
//		Batch.setProcessed(false);
		Batch.saveEx();
		
		reversalBatch.setReversal_ID(Batch.getGL_JournalBatch_ID());
		
		MJournal reversalJournal = reversalBatch.getJournals(true)[0];
		MJournal Journal = new MJournal(Batch);
		Journal.setDocumentNo("!!!"+reversalJournal.getDocumentNo());
		Journal.setDescription("{->" + reversalJournal.getDocumentNo() + ")");
		Journal.setC_DocType_ID(1000000);
		Journal.setDateDoc(reversalJournal.getDateDoc());
		Journal.setDateAcct(reversalJournal.getDateAcct());
		Journal.setC_Period_ID(Period.getC_Period_ID());//get current period!
		Journal.setC_Currency_ID(reversalJournal.getC_Currency_ID());
		Journal.setC_AcctSchema_ID(1000000);
		Journal.setGL_Category_ID(1000000);
		Journal.setC_ConversionType_ID(1000001);
		Journal.setReversal_ID(reversalJournal.getGL_Journal_ID());
		Journal.setC_ConversionType_ID(reversalJournal.getC_ConversionType_ID()); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//		Journal.setProcessing(false);
//		Journal.setProcessed(false);
//		Journal.setPosted(false);
		
		Journal.saveEx();
		reversalJournal.setReversal_ID(Journal.getGL_Journal_ID());
		
		MJournalLine[] reversalLines = reversalJournal.getLines(true);
		for(MJournalLine reversalLine:reversalLines  ) {
	    	MJournalLine JournalLine = new MJournalLine(Journal);
			JournalLine.setDescription("{->" + reversalLine.getDescription() + ")");
			JournalLine.setC_Currency_ID(reversalLine.getC_Currency_ID());
			JournalLine.sethrm_reserve_ID(reversalLine.gethrm_reserve_ID());
			JournalLine.sethrm_reservesectional_ID(reversalLine.gethrm_reservesectional_ID());
			JournalLine.setLine(reversalLine.getLine());
			JournalLine.setC_ValidCombination_ID(reversalLine.getC_ValidCombination_ID());
			JournalLine.setAmtSourceDr(reversalLine.getAmtSourceDr().negate());
			JournalLine.setAmtSourceCr(reversalLine.getAmtSourceCr().negate());
			JournalLine.setAmtAcctDr(reversalLine.getAmtAcctDr().negate());
			JournalLine.setAmtAcctCr(reversalLine.getAmtAcctCr().negate());
			JournalLine.setProcessed(true);
			JournalLine.setA_CreateAsset(false);
			JournalLine.setA_Processed(false);
			JournalLine.saveEx();
/*			
			MFactAcct acct = new MFactAcct(getCtx(), null, hrmpayment.get_TrxName());
			acct.setAmtAcctCr(reversalLine.getAmtAcctCr().negate());
			acct.setAmtAcctDr(reversalLine.getAmtAcctDr().negate());					
			acct.setAmtSourceCr(reversalLine.getAmtSourceCr().negate());
			acct.setAmtSourceDr(reversalLine.getAmtSourceDr().negate());
			acct.setAccount_ID(reversalLine.getAccount().getAccount_ID());
			acct.setC_AcctSchema_ID(as.getAcctSchemaGL().getC_AcctSchema_ID());
			acct.setC_Period_ID(Journal.getC_Period_ID());
			acct.setAD_Table_ID(MTable.getTable_ID("GL_Journal")); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			acct.setRecord_ID(Journal.get_ID());
			acct.setGL_Category_ID(Batch.getGL_Category_ID()); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			acct.setC_Currency_ID(Journal.getC_Currency_ID()); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			acct.setDateAcct(Journal.getDateAcct());
			acct.setDateTrx(Journal.getDateAcct());
			acct.setPostingType(Fact.POST_Actual);
			acct.save();
*/			
		}
	}

	/**
	 * @param hrmpayment
	 * @return
	 */
	private MJournalBatch getBatch(Mhrmpayment hrmpayment) {
		MJournalBatch Batch = null; //TODO Как найти Batch?
		
		X_C_Period Period = Util.getPeriod(hrmpayment.getDateFrom());
		String batchNo ="HR Резерв: " + hrmpayment.getName(); 
		String sql = "SELECT * FROM GL_JournalBatch WHERE DocStatus = 'CO' AND C_Doctype_ID = 1000000 AND DocumentNo like ? AND C_Period_ID = ?";
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try{
			pstmt = DB.prepareStatement(sql, null);
			pstmt.setString(1, batchNo);
			pstmt.setInt(2, Period.getC_Period_ID());
			rs = pstmt.executeQuery();
			if (rs.next()) {
				Batch = new MJournalBatch(Env.getCtx(),rs,hrmpayment.get_TrxName());
			}
		} catch(SQLException e) {
			log.log(Level.WARNING, e.getLocalizedMessage());
		} finally {
			DB.close(rs, pstmt);
			pstmt = null;
		}
		return Batch;
	}

	/**
	 * @param hrmpayment
	 * @param as
	 * @return
	 */
	private ArrayList<Fact> makeCorrectFact(Mhrmpayment hrmpayment,	MAcctSchema as) {
		ArrayList<Fact> facts = new ArrayList<Fact>();

		int Reversal_ID = hrmpayment.getReversal_ID();
		Mhrmpayment reversal = new Mhrmpayment(getCtx(),Reversal_ID,hrmpayment.get_TrxName());
//		ResultSet rs = getResultSet(reversal);
		
		String sql = "SELECT * FROM hrm_payment WHERE hrm_payment_id = ?";
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try{
			pstmt = DB.prepareStatement(sql, null);
			pstmt.setInt(1, hrmpayment.gethrm_payment_ID());
			rs = pstmt.executeQuery();
			if (rs != null) {
				MAcctSchema[] ass = as.getClientAcctSchema(getCtx(), Env.getAD_Client_ID(getCtx()));
				Doc_hrmpayment reversalDoc = (Doc_hrmpayment) Doc.get(ass, MTable.getTable_ID(reversal.get_TableName()), reversal.gethrm_payment_ID(), getTrxName());
				
//				Fact factReversal = new Fact(reversalDoc,as,Fact.POST_Actual);
				
				String sql1 = "SELECT * FROM Fact_Acct \n"
						    + "WHERE AD_Org_ID = ? \n"
						    + "  AND AD_Client_ID = ? \n"
						    + "  AND AD_Table_ID = ? \n"
						    + "  AND Record_ID = ? \n "
						    + "  AND PostingType = ? \n";
				int temp_AD_Org_ID = reversalDoc.getAD_Org_ID();
				int temp_AD_Cleint_ID = reversalDoc.getAD_Client_ID();
				int temp_AD_Table_ID = MTable.getTable_ID(hrmpayment.get_TableName());
				int temp_Record_ID = Reversal_ID;
				String temp_PostingType = Fact.POST_Actual; 
				PreparedStatement pstmt1 = null;
				ResultSet rs1 = null;
				Fact fact = new Fact(this, as, Fact.POST_Actual);
				try {
					pstmt1 = DB.prepareStatement(sql1, hrmpayment.get_TrxName());
					pstmt1.setInt(1, temp_AD_Cleint_ID);
					pstmt1.setInt(2, temp_AD_Org_ID);
					pstmt1.setInt(3, temp_AD_Table_ID);
					pstmt1.setInt(4, temp_Record_ID);
					pstmt1.setString(5, temp_PostingType);
					rs1 = pstmt1.executeQuery();
					while(rs1.next()) {
						MFactAcct fa = new MFactAcct(Env.getCtx(),rs1,hrmpayment.get_TrxName());
						MAccount account = getAccount(fa,as); // TODO 
						FactLine fl = fact.createLine(null, account,fa.getC_Currency_ID(), fa.getAmtAcctDr().negate(), fa.getAmtAcctCr().negate());
					}
				} catch(SQLException e) {
					log.log(Level.WARNING, e.getLocalizedMessage());
				} finally {
					DB.close(rs1, pstmt1);
					rs1 =null;
					pstmt1 = null;
				}
				facts.add(fact);
			}
		} catch(SQLException e) {
			log.log(Level.WARNING, e.getLocalizedMessage());
		} finally {
			DB.close(rs, pstmt);
			rs =null;
			pstmt = null;
		}
		
		return facts;
	}
	
	/**
	 * @param fa
	 * @return
	 */
	private MAccount getAccount(MFactAcct fa,	MAcctSchema as) {
		//TODO Сделать под общий вариант!
		MAccount result = null;
		MAccount acct7210 = getAccount(Doc.ACCTTYPE_HRMBankInTransit, as); //7210
		MAccount acct3120 = getAccount(Doc.ACCTTYPE_HRMIPN, as);	//3120
		MAccount acct3150 = getAccount(Doc.ACCTTYPE_HRMCNALOG, as);	//3150
		MAccount acct3210 = getAccount(Doc.ACCTTYPE_HRMCOTCH, as);	//3210
		MAccount acct3220 = getAccount(Doc.ACCTTYPE_HRMOPV, as);	//3220
		MAccount acct3350 = getAccount(Doc.ACCTTYPE_HRMSalary, as);	//3350
		MAccount acct3430 = getAccount(Doc.ACCTTYPE_HRMREZERV, as); //3430
		if (acct7210.getAccount().getC_ElementValue_ID() == fa.getAccount_ID()) {
			result = acct7210; 
		} else if (acct3120.getAccount().getC_ElementValue_ID() == fa.getAccount_ID()) {
			result = acct3120; 
		} else if (acct3150.getAccount().getC_ElementValue_ID() == fa.getAccount_ID()) {
			result = acct3150; 
		} else if (acct3210.getAccount().getC_ElementValue_ID() == fa.getAccount_ID()) {
			result = acct3210; 
		} else if (acct3220.getAccount().getC_ElementValue_ID() == fa.getAccount_ID()) {
			result = acct3220; 
		} else if (acct3350.getAccount().getC_ElementValue_ID() == fa.getAccount_ID()) {
			result = acct3350; 
		} else if (acct3430.getAccount().getC_ElementValue_ID() == fa.getAccount_ID()) {
			result = acct3430; 
		}
		return result;
	}

	private BigDecimal getSaldo(int Account_ID, int C_BPartner_ID, Timestamp dateacct) {
		BigDecimal result = new BigDecimal(0);
		
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String sql = " select fa.ad_org_id \n"
                    +", fa.ad_client_id \n"
                    +", fa.account_id \n"
                    +", fa.c_bpartner_id \n" 
                    +", sum(fa.amtacctdr) as amtacctdr \n"
                    +", sum(fa.amtacctcr) as amtacctcr \n"
                    +", sum(fa.amtacctcr) - sum(fa.amtacctdr) as saldo \n"
                    +" from adempiere.fact_acct fa \n"
                    +" where fa.account_id =" + Account_ID + " \n" 
                    +" and fa.c_bpartner_id =" + C_BPartner_ID + " \n"
                    +" and fa.dateacct between DATE_TRUNC('MONTH',"+DB.TO_DATE(dateacct, true)+") " +
                    		"and (DATE_TRUNC('MONTH',"+DB.TO_DATE(dateacct, true)+") + INTERVAL '1 MONTH' - INTERVAL '1 DAY')::DATE \n"
                    + " and fa.ad_table_id <> 1000044 \n"		
                    + " and fa.ad_table_id <> 335 \n"		
                    +"group by fa.ad_org_id \n"
                    +"       , fa.ad_client_id \n"
                    +"       , fa.account_id \n"
                    +"       , fa.c_bpartner_id \n" ;
		try{
			log.log(Level.INFO, sql);
			pstmt = DB.prepareStatement(sql, null);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				result = rs.getBigDecimal("saldo");
			}
		}catch(SQLException e){
			log.log(Level.WARNING, e.getLocalizedMessage());
		}
		finally
		{
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}
		
		return result;
	}

	public int checkValidCombination(int account_ID, int C_BPartner_ID){
		
		String sql = " select c_validcombination_id from adempiere.c_validcombination where account_id = " + account_ID + " and c_bpartner_id = " + C_BPartner_ID;
		
		int AccountValid = 0;
		
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try{
			pstmt = DB.prepareStatement(sql, null);
			rs = pstmt.executeQuery();
			while (rs.next()) {
				AccountValid = rs.getInt(1);
			}
		}catch(SQLException e){
			log.log(Level.WARNING, e.getLocalizedMessage());
		}
		finally
		{
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}
		
		return AccountValid;

		
	}
	
	
	/**
	 * 	Create Fact Cash Based (i.e. only revenue/expense)
	 *	@param as accounting schema
	 *	@param fact fact to add lines to
	 *	@param multiplier source amount multiplier
	 *	@return accounted amount
	 */
	public BigDecimal createFactCash (MAcctSchema as, Fact fact, BigDecimal multiplier)
	{
		boolean creditMemo = getDocumentType().equals(DOCTYPE_ARCredit)
			|| getDocumentType().equals(DOCTYPE_APCredit);
		boolean payables = getDocumentType().equals(DOCTYPE_APInvoice)
			|| getDocumentType().equals(DOCTYPE_APCredit);
		BigDecimal acctAmt = Env.ZERO;
		FactLine fl = null;
		//	Revenue/Cost
		for (int i = 0; i < p_lines.length; i++)
		{
			DocLine line = p_lines[i];
			boolean landedCost = false;
			if  (payables)
				landedCost = landedCost(as, fact, line, false);
			if (landedCost && as.isExplicitCostAdjustment())
			{
				fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
					getC_Currency_ID(), null, line.getAmtSource());
				//
				fl = fact.createLine (line, line.getAccount(ProductCost.ACCTTYPE_P_Expense, as),
					getC_Currency_ID(), line.getAmtSource(), null);
				String desc = line.getDescription();
				if (desc == null)
					desc = "100%";
				else
					desc += " 100%";
				fl.setDescription(desc);
			}
			if (!landedCost)
			{
				MAccount acct = line.getAccount(
					payables ? ProductCost.ACCTTYPE_P_Expense : ProductCost.ACCTTYPE_P_Revenue, as);
				if (payables)
				{
					//	if Fixed Asset
					if (line.isItem())
						acct = line.getAccount (ProductCost.ACCTTYPE_P_InventoryClearing, as);
				}
				BigDecimal amt = line.getAmtSource().multiply(multiplier);
				BigDecimal amt2 = null;
				if (creditMemo)
				{
					amt2 = amt;
					amt = null;
				}
				if (payables)	//	Vendor = DR
					fl = fact.createLine (line, acct,
						getC_Currency_ID(), amt, amt2);
				else			//	Customer = CR
					fl = fact.createLine (line, acct,
						getC_Currency_ID(), amt2, amt);
				if (fl != null)
					acctAmt = acctAmt.add(fl.getAcctBalance());
			}
		}
		//  Tax
		for (int i = 0; i < m_taxes.length; i++)
		{
			BigDecimal amt = m_taxes[i].getAmount();
			BigDecimal amt2 = null;
			if (creditMemo)
			{
				amt2 = amt;
				amt = null;
			}
			FactLine tl = null;
			if (payables)
				tl = fact.createLine (null, m_taxes[i].getAccount(m_taxes[i].getAPTaxType(), as),
					getC_Currency_ID(), amt, amt2);
			else
				tl = fact.createLine (null, m_taxes[i].getAccount(DocTax.ACCTTYPE_TaxDue, as),
					getC_Currency_ID(), amt2, amt);
			if (tl != null)
				tl.setC_Tax_ID(m_taxes[i].getC_Tax_ID());
		}
		//  Set Locations
		FactLine[] fLines = fact.getLines();
		for (int i = 0; i < fLines.length; i++)
		{
			if (fLines[i] != null)
			{
				if (payables)
				{
					fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), true);  //  from Loc
					fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), false);    //  to Loc
				}
				else
				{
					fLines[i].setLocationFromOrg(fLines[i].getAD_Org_ID(), true);    //  from Loc
					fLines[i].setLocationFromBPartner(getC_BPartner_Location_ID(), false);  //  to Loc
				}
			}
		}
		return acctAmt;
	}	//	createFactCash
	
	
	/**
	 * 	Create Landed Cost accounting & Cost lines
	 *	@param as accounting schema
	 *	@param fact fact
	 *	@param line document line
	 *	@param dr DR entry (normal api)
	 *	@return true if landed costs were created
	 */
	private boolean landedCost (MAcctSchema as, Fact fact, DocLine line, boolean dr) 
	{
		int C_InvoiceLine_ID = line.get_ID();
		MLandedCostAllocation[] lcas = MLandedCostAllocation.getOfInvoiceLine(
			getCtx(), C_InvoiceLine_ID, getTrxName());
		if (lcas.length == 0)
			return false;
		
		//	Calculate Total Base
		double totalBase = 0;
		for (int i = 0; i < lcas.length; i++)
			totalBase += lcas[i].getBase().doubleValue();
		
		//	Create New
		MInvoiceLine il = new MInvoiceLine (getCtx(), C_InvoiceLine_ID, getTrxName());
		for (int i = 0; i < lcas.length; i++)
		{
			MLandedCostAllocation lca = lcas[i];
			if (lca.getBase().signum() == 0)
				continue;
			double percent = lca.getBase().doubleValue() / totalBase;
			String desc = il.getDescription();
			if (desc == null)
				desc = percent + "%";
			else
				desc += " - " + percent + "%";
			if (line.getDescription() != null)
				desc += " - " + line.getDescription(); 
			
			//	Accounting
			ProductCost pc = new ProductCost (Env.getCtx(), 
				lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(), getTrxName());
			BigDecimal drAmt = null;
			BigDecimal crAmt = null;
			if (dr)
				drAmt = lca.getAmt();
			else
				crAmt = lca.getAmt();
			FactLine fl = fact.createLine (line, pc.getAccount(ProductCost.ACCTTYPE_P_CostAdjustment, as),
				getC_Currency_ID(), drAmt, crAmt);
			fl.setDescription(desc);
			fl.setM_Product_ID(lca.getM_Product_ID());
			
			//	Cost Detail - Convert to AcctCurrency
			BigDecimal allocationAmt =  lca.getAmt();
			if (getC_Currency_ID() != as.getC_Currency_ID())
				allocationAmt = MConversionRate.convert(getCtx(), allocationAmt, 
					getC_Currency_ID(), as.getC_Currency_ID(),
					getDateAcct(), getC_ConversionType_ID(), 
					getAD_Client_ID(), getAD_Org_ID());
			if (allocationAmt.scale() > as.getCostingPrecision())
				allocationAmt = allocationAmt.setScale(as.getCostingPrecision(), BigDecimal.ROUND_HALF_UP);
			if (!dr)
				allocationAmt = allocationAmt.negate();
			// AZ Goodwill
			// use createInvoice to create/update non Material Cost Detail
			MCostDetail.createInvoice(as, lca.getAD_Org_ID(), 
					lca.getM_Product_ID(), lca.getM_AttributeSetInstance_ID(),
					C_InvoiceLine_ID, lca.getM_CostElement_ID(),
					allocationAmt, lca.getQty(),
					desc, getTrxName());
			// end AZ
		}
		
		log.config("Created #" + lcas.length);
		return true;
	}	//	landedCosts
	
}   //  Doc_HRM
